//
//  ComputingPowerService.swift
//  SCA
//
//  Created by tjun on 2025/9/11.
//

import Foundation

struct ReceiveAwardInfo {
    let total_amount_disp: String
    let claim_amount_disp: String
    let claimable: Bool
    let total_amount: String
    let models: [ReceiveAwardModel]
}

struct CoinConvertModel {
    let value_disp: String
    let amount_disp: String
    let claimable: Bool
    let amount: String
    let wallet: String
    let icon: String
    let coinName: String
}

struct BuyPowerWalletModel {
    let title: String
    let decimal: Int
    let coin: String
    let viewDecimal: Int
    let icon: String
}

struct BuyPowerOptionModel {
    let title: String
    let min: Int
    let max: Int
    let info: String
    let invest: Int
    let investDisp: String
    let paymentMix: Bool
    
    init(title: String, min: Int, max: Int, info: String, invest: Int, investDisp: String, paymentMix: Bool) {
        self.title = title
        self.min = min
        self.max = max
        self.info = info
        self.invest = invest
        self.investDisp = investDisp
        self.paymentMix = paymentMix
    }
}

class BuyPowerPaymentOption {
    let coin: String
    let coinName: String
    let coinUrl: String
    let amount: String
    let displayAmount: String
    var isSelected: Bool = false
    
    init(coin: String, coinName: String, coinUrl: String, amount: String, displayAmount: String) {
        self.coin = coin
        self.coinName = coinName
        self.coinUrl = coinUrl
        self.amount = amount
        self.displayAmount = displayAmount
    }
}

class BuyPowerModel {
    
    let maxCap: String
    let maxCount: String
    let commitCodeHint: String
    let walletModels: [String: BuyPowerWalletModel]
    let options: [String: [BuyPowerOptionModel]]
    let paymentOptions: [BuyPowerPaymentOption]
    
    init(maxCap: String, maxCount: String, commitCodeHint: String, options: [String: [BuyPowerOptionModel]], walletModels: [String: BuyPowerWalletModel], paymentOptions: [BuyPowerPaymentOption]) {
        self.maxCap = maxCap
        self.maxCount = maxCount
        self.commitCodeHint = commitCodeHint
        self.options = options
        self.walletModels = walletModels
        self.paymentOptions = paymentOptions
    }
}


struct PreviewBuyComputingPowerModel {
    
    struct PreviewItem {
        let title: String
        let value: String
        let type: String
        let display: String
        
        init(dict: [String: Any]) {
            self.title = dict.stringValue("title")
            self.value = dict.stringValue("value")
            self.type = dict.stringValue("type")
            self.display = dict.stringValue("display")
        }
    }
    
    let title: String
    let playCoinUrl: String
    let playCoinName: String
    let playCoin: String
    let payment: PreviewItem
    let apr: PreviewItem
    let power: PreviewItem
    let ev: PreviewItem
    let investment: PreviewItem
}


class ComputingPowerService {
    
    static func loadPoolData(success:(([PowerListModel]) -> Void)? = nil, failure:((_ error: Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: APIEndpoint.poolStackList, parameters: nil, success: { data in
            
            if let result = data as? [String: Any],
               let active = result["active"] as? [String: Any] {
                   
                   var models: [PowerListModel] = []
                   
                   for (key, value) in active {
                       guard let dict = value as? [String: Any] else { continue }
                       
                       if let info = dict["info"] as? [String: Any],
                          let overview = dict["overview"] as? [String: Any],
                          let bonus = info["bonus"] as? [String: Any],
                          let wallet = bonus["wallet"] as? [String: Any],
                          let title = info["title"] as? String,
                          let subtitle = info["subtitle"] as? String,
                          let desc = info["desc"] as? String,
                          let icon = info["icon"] as? String,
                          let total = overview["total"] as? String,
                          let total_disp = overview["total_disp"] as? String,
                          let apr = overview["apr"] as? String,
                          let apr_disp = overview["apr_disp"] as? String {
                           
                           let iconDicts = wallet.values  // 这里应该是 [[String: Any]]
                           var icons: [String] = []
                           for dict in iconDicts {
                               if let dict = dict as? [String: Any],
                                  let icon = dict["icon"] as? String {
                                   icons.append(icon)
                               }
                           }
                           let sortIcons = icons.sorted { $0 > $1 }
                           printf("icons=\(sortIcons)")
                           
                           let powerListModel = PowerListModel(title: title, subtitle: subtitle, description: desc, icon: icon, total: total, totalDisp: total_disp, icons: sortIcons, aprDisp: apr_disp, apr: apr, pool: key)
                           models.append(powerListModel)
                       }
                   }
                   
                   let sortModels = models.sorted { $0.pool > $1.pool }
                   success?(sortModels)
                   
               } else {
                   failure?(SCAError.dataException)
               }
        }, failure: failure)
    }
    
    
    static func loadPowerListData(success:(([PurchasePowerListModel]) -> Void)? = nil, failure:((_ error: Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: APIEndpoint.stackProductList, parameters: nil, success: { data in
            
            if let result = data as? [String: Any] {
                
                var models: [PurchasePowerListModel] = []
                
                for (key, value) in result {
                    
                    guard let dict = value as? [String: Any] else { continue }
                    
                    if let bonus = dict["bonus"] as? [String: Any],
                       let wallet = bonus["wallet"] as? [String: Any],
                       let title = dict["title"] as? String,
                       let subtitle = dict["subtitle"] as? String,
                       let desc = dict["desc"] as? String,
                       let poolIcon = dict["icon"] as? String,
                       let apr_disp = bonus["apr_disp"] as? String {
                        
                        printf("title=\(title)")
                        printf("subtitle=\(subtitle)")
                        printf("icon=\(poolIcon)")
                        printf("apr_disp=\(apr_disp)")
                        
                        let iconDicts = wallet.values  // 这里应该是 [[String: Any]]
                        var icons: [String] = []
                        for dict in iconDicts {
                            if let dict = dict as? [String: Any],
                               let icon = dict["icon"] as? String {
                                icons.append(icon)
                            }
                        }
                        let sortIcons = icons.sorted { $0 > $1 }
                        printf("icons=\(sortIcons)")
                        
                        let powerListModel = PurchasePowerListModel(title: title, subtitle: subtitle, description: desc, pool: key, poolIcon: poolIcon, icons: sortIcons, aprDisp: apr_disp)
                        
                        models.append(powerListModel)
                    }
                    
                    let sortModels = models.sorted { $0.pool > $1.pool }
                    success?(sortModels)
                }
                
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
        
    }
    
    
    static func loadPowerDetailData(pool: String, success:(([PowerDetailModel], Int) -> Void)? = nil, failure:((_ error: Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: String(format: APIEndpoint.powerList, pool), parameters: nil, success: { data in
            
            if let result = data as? [String: Any],
               let datalist = result["datalist"] as? [String: Any],
               let list = datalist["data"] as? [String: Any],
               let total = datalist["total_record"] as? Int {
                
                var models: [PowerDetailModel] = []
                
                for (key, value) in list {
                    
                    guard let dict = value as? [String: Any] else { continue }
                    
                    models.append(PowerDetailModel(dict: dict))
                }
                
                let sortModels = models.sorted { $0.Id > $1.Id }
                success?(sortModels, total)
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
        
    }
    
    //    static let powerInfo = "/pool/%@/stack/power"
    //    static let powerList = "/pool/%@/stack/info"
    
    static func loadReceiveAwardData(success:((ReceiveAwardInfo) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: APIEndpoint.receiveAward, parameters: ["step": "ini"], success: { data in
            if let result = data as? [String: Any],
               let resultData = result["data"] as? [String: Any] {
                
                let total_amount = result.stringValue("total_amount")
                let total_amount_disp = result.stringValue("total_amount_disp")
                let claim_amount_disp = result.stringValue("claim_amount_disp")
                let claimable = result.boolValue("claimable")
                
                var models: [ReceiveAwardModel] = []
                
                for (coin, dict) in resultData {
                    guard let coinInfo = dict as? [String: Any], let conf = coinInfo["conf"] as? [String: Any] else { continue }
                    
                    guard let title = conf["title"] as? String,
                          let icon = conf["icon"] as? String,
                          let amount_disp = coinInfo["amount_disp"] as? String,
                          let value_disp = coinInfo["value_disp"] as? String,
                          let valueRatio = conf["value_ratio"] as? String else { continue }
                    
                    models.append(ReceiveAwardModel(valueDisp: value_disp, amountDisp: amount_disp, title: title, icon: icon, coin: coin, valueRatio: valueRatio))
                }
                
                let sortModels = models.sorted { $0.icon > $1.icon }
                printf("sortModels=\(sortModels)")
                success?(ReceiveAwardInfo(total_amount_disp: total_amount_disp, claim_amount_disp: claim_amount_disp, claimable: claimable, total_amount: total_amount, models: sortModels))
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
    }
    
    
    static func receiveAward(success:(() -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        NetworkManager.shared.post(url: APIEndpoint.receiveAward, parameters: nil, success: { data in
            if let result = data as? [String: Any],
               let isSuccess = result["success"] as? Bool,
               isSuccess {
                success?()
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
    }
    
    static func loadConvertData(success:((CoinConvertModel) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: APIEndpoint.convert, parameters: ["step": "ini"], success: { data in
            if let result = data as? [String: Any],
               let conf = result["conf"] as? [String: Any],
               let confData = result["data"] as? [String: Any] {
                
                let icon = conf.stringValue("icon")
                let coinName = conf.stringValue("title")
                let value_disp = confData.stringValue("value_disp")
                let amount = confData.stringValue("amount")
                let amount_disp = confData.stringValue("amount_disp")
                let wallet = confData.stringValue("wallet")
                let claimable = confData.boolValue("claimable")
                
                success?(CoinConvertModel(value_disp: value_disp, amount_disp: amount_disp, claimable: claimable, amount: amount, wallet: wallet, icon: icon, coinName: coinName))
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
    }
    
    
    static func convert(success:(() -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        NetworkManager.shared.post(url: APIEndpoint.convert, parameters: nil, success: { data in
            if let _ = data as? [String: Any] {
                success?()
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
    }
    
    static func loadBuyComputingPower(pool: String, success:((BuyPowerModel) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        NetworkManager.shared.post(url: String(String(format: APIEndpoint.buyComputingPower, pool)), parameters: [
            "step": "ini"
        ], success: { data in
            if let result = data as? [String: Any],
               let payment_option = result["payment_option"] as? [String: String],
               let commitment_code = result["commitment_code"] as? [String: Any],
               let conf = result["conf"] as? [String: Any],
               let bonus = conf["bonus"] as? [String: Any],
               let optionDict = conf["option"] as? [String: Any],
               let wallet_conf = result["wallet_conf"] as? [String: Any] {
                
                let max_count = conf.stringValue("max_count")
                let max_cap = bonus.stringValue("max_cap")
                let commitment_code_hint = commitment_code.stringValue("info")
                
                var walletModels: [String: BuyPowerWalletModel] = [:]
                
                for (coin, dict) in wallet_conf {
                    guard let coinInfo = dict as? [String: Any] else { continue }
                    
                    guard let title = coinInfo["title"] as? String,
                          let icon = coinInfo["icon"] as? String,
                          let decimal = coinInfo["decimal"] as? Int,
                          let viewDecimal = coinInfo["view_decimal"] as? Int  else { continue }
                    walletModels[coin] = BuyPowerWalletModel(title: title, decimal: decimal, coin: coin, viewDecimal: viewDecimal, icon: icon)
                }
                
                var options: [String: [BuyPowerOptionModel]] = [:]
                
                for (groupKey, value) in optionDict {
                    guard let items = value as? [String: Any] else { continue }
                    var groupArray: [BuyPowerOptionModel] = []
                    for (_, itemValue) in items {
                        
                        if let item = itemValue as? [String: Any],
                           let title = item["title"] as? String,
                           let info = item["info"] as? String,
                           let investDisp = item["invest_disp"] as? String,
                           let min = item["min"] as? Int,
                           let max = item["max"] as? Int,
                           let payment_mix = item["payment_mix"] as? Bool,
                           let invest = item["invest"] as? Int {
                            
                            groupArray.append(BuyPowerOptionModel(title: title, min: min, max: max, info: info, invest: invest, investDisp: investDisp, paymentMix: payment_mix))
                        }
                    }
                    
                    let sortGroupArray = groupArray.sorted { $0.invest < $1.invest }
                    options[groupKey] = sortGroupArray
                }
                
                
                var paymentOptions: [BuyPowerPaymentOption] = []
                
                for (code, rawValue) in payment_option {
                    // rawValue 形如 "USCA: 6,630.50"
                    
                    var coinUrl = ""
                    if let optionModel = walletModels[code] {
                        coinUrl = optionModel.icon
                    }
                    
                    let parts = rawValue.split(separator: ":").map { $0.trimmingCharacters(in: .whitespaces) }
                    if parts.count == 2 {
                        let name = parts[0]
                        let value = parts[1]
                        paymentOptions.append(BuyPowerPaymentOption(coin: code, coinName: name, coinUrl: coinUrl, amount: value, displayAmount: rawValue))
                    }
                }
                
                let sortPaymentOptions = paymentOptions.sorted { $0.coin > $1.coin }
                
                success?(BuyPowerModel(maxCap: max_cap, maxCount: max_count, commitCodeHint: commitment_code_hint, options: options, walletModels: walletModels, paymentOptions: sortPaymentOptions))
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
    }
    
    static func previewBuyComputingPower(coin: String, pool: String, commitmentCode: String, invest100: Bool, payment: Float, paymentMix: String, success:((PreviewBuyComputingPowerModel) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: String(String(format: APIEndpoint.buyComputingPower, pool)), parameters: [
            "commitment_code": commitmentCode,
            "invest_100": invest100 ? 1 : 0,
            "invest_2088": invest100 ? 0 : 1,
            "payment": payment,
            "payment_mix": paymentMix,
            "wallet": coin,
            "step": "preview"
        ], success: { data in
            if let result = data as? [String: Any],
               let wallet_conf = result["wallet_conf"] as? [String: Any],
               let inputDict = result["input"] as? [String: Any],
               let wallet = inputDict["wallet"] as? [String: Any],
               let aprDict = inputDict["apr"] as? [String: Any],
               let powerDict = inputDict["power"] as? [String: Any],
               let evDict = inputDict["ev"] as? [String: Any],
               let paymentDict = inputDict["payment"] as? [String: Any],
               let investmentDict = inputDict["investment"] as? [String: Any] {
                
                var walletModels: [String: BuyPowerWalletModel] = [:]
                
                for (coin, dict) in wallet_conf {
                    guard let coinInfo = dict as? [String: Any] else { continue }
                    
                    guard let title = coinInfo["title"] as? String,
                          let icon = coinInfo["icon"] as? String,
                          let decimal = coinInfo["decimal"] as? Int,
                          let viewDecimal = coinInfo["view_decimal"] as? Int  else { continue }
                    walletModels[coin] = BuyPowerWalletModel(title: title, decimal: decimal, coin: coin, viewDecimal: viewDecimal, icon: icon)
                }
                
                
                var playCoinUrl = ""
                let playCoin = wallet.stringValue("value")
                let title = wallet.stringValue("title")
                let playCoinName = wallet.stringValue("display")
                
                if let walletModel = walletModels[coin] {
                    playCoinUrl = walletModel.icon
                }
                
                success?(PreviewBuyComputingPowerModel(title: title, playCoinUrl: playCoinUrl, playCoinName: playCoinName, playCoin: playCoin,  payment: PreviewBuyComputingPowerModel.PreviewItem(dict: paymentDict), apr: PreviewBuyComputingPowerModel.PreviewItem(dict: aprDict), power: PreviewBuyComputingPowerModel.PreviewItem(dict: powerDict), ev: PreviewBuyComputingPowerModel.PreviewItem(dict: evDict), investment: PreviewBuyComputingPowerModel.PreviewItem(dict: investmentDict)))
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
    }
        
    static func buyComputingPower(coin: String, pool: String, commitmentCode: String, password: String, invest100: Bool, payment: Float, paymentMix: String, success:((String) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: String(String(format: APIEndpoint.buyComputingPower, pool)), parameters: [
            "commitment_code": commitmentCode,
            "invest_100": invest100 ? 1 : 0,
            "invest_2088": invest100 ? 0 : 1,
            "payment": payment,
            "payment_mix": paymentMix,
            "wallet": coin,
            "pin_code": password
        ], success: { data in
            if let result = data as? [String: Any],
               let isSuccess = result["success"] as? Bool,
               isSuccess,
               let success_msg = result["success_msg"] as? String {
                success?(success_msg)
            } else {
                failure?(SCAError.dataException)
            }
        }, failure: failure)
    }
    
    static func loadExtractRecordData(isTeam: Bool = false, success:(([ExtractRecordsListModel], Int) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        
        var parameters: [String: Any] = [:]
        if isTeam {
            parameters["type"] = "bonus"
        } else {
            parameters["type"] = ""
        }
        
        NetworkManager.shared.post(url: APIEndpoint.extractRecord, parameters: parameters, success: { data in
            guard let result = data as? [String: Any],
                  let dataList = result["datalist"] as? [String: Any],
                  let data = dataList["data"] as? [String: Any]
            else {
                failure?(SCAError.dataException)
                return
            }
            
            let total = dataList.intValue("total_record")
            
            var models: [ExtractRecordsListModel] = []
            
            for (sortKey, dataValue) in data {
                guard let dict = dataValue as? [String: Any] else {
                    continue
                }
                
                let date = dict.stringValue("cdate")
                let coinName = dict.stringValue("wallet_disp")
                let amount = dict.stringValue("amount_disp")
                models.append(ExtractRecordsListModel(date: formatDate(date, dateFormat: "yyyy-MM-dd"), coinName: coinName, amount: amount, sortKey: sortKey))
            }
            
            let sortModels = models.sorted { $0.sortKey > $1.sortKey }
            success?(sortModels, total)
            
        }, failure: failure)
        
    }
    
    
    static func loadCastingEarningsDetailsData(pool: String, Id: Int, success:(([CastingEarningsRecordModel], String) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: String(format: APIEndpoint.castingEarningsDetails, pool, String(Id)), success: { data in
            guard let result = data as? [String: Any],
                  let dataList = result["datalist"] as? [String: Any],
                  let bonus = dataList["bonus"] as? [String: Any],
                  let data = dataList["data"] as? [String: Any]
            else {
                failure?(SCAError.dataException)
                return
            }
            
            let totalAmount = bonus.stringValue("total")
            var models: [CastingEarningsRecordModel] = []
            
            for (sortKey, dataValue) in data {
                
                guard let dict = dataValue as? [String: Any] else {
                    continue
                }
                
                let date = dict.stringValue("cdate")
                let typeDisp = dict.stringValue("type_disp")
                let amount = dict.stringValue("amount_disp")
                
                models.append(CastingEarningsRecordModel(date: formatDate(date), amount: amount, sortKey: sortKey))
            }
            
            let sortModels = models.sorted { $0.sortKey < $1.sortKey }
            success?(sortModels, totalAmount)
            
        }, failure: failure)
        
    }
    
    static func loadEarningsDetailsData(pool: String, success:(([EarningsRecordModel], String) -> Void)? = nil, failure:((Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: String(format: APIEndpoint.earningsDetails, pool), success: { data in
            guard let result = data as? [String: Any],
                  let dataList = result["datalist"] as? [String: Any],
                  let bonus = dataList["bonus"] as? [String: Any],
                  let data = dataList["data"] as? [String: Any]
            else {
                failure?(SCAError.dataException)
                return
            }
            
            let totalAmount = bonus.stringValue("total")
            var models: [EarningsRecordModel] = []
            
            for (sortKey, dataValue) in data {
                
                guard let dict = dataValue as? [String: Any] else {
                    continue
                }
                
                let date = dict.stringValue("cdate")
                let typeDisp = dict.stringValue("type_disp")
                let amount = dict.stringValue("amount_disp")
                
                models.append(EarningsRecordModel(date: formatDate(date, dateFormat: "yyyy-MM-dd"), typeDisp: typeDisp, amount: amount, sortKey: sortKey))
            }
            
            let sortModels = models.sorted { $0.sortKey < $1.sortKey }
            success?(sortModels, totalAmount)
            
        }, failure: failure)
        
    }
    
    static func loadPersonalPowerOverviewData(completion:((PowerInfo) -> Void)? = nil) {
        if let tokensPrice = UserDefaults.standard.value(forKey: "personalPowerOverview") as? String {
            if let result = tokensPrice.toObject() as? [String: Any],
                let power = result["power"] as? [String: Any] {
                
                completion?(PowerInfo(dict: power))
            }
        }
        
        NetworkManager.shared.post(url: APIEndpoint.personalPowerOverview, success: { data in
            guard let result = data as? [String: Any],
                  let power = result["power"] as? [String: Any] else {
                return
            }
            
            if let jsonString = result.toJSONString() {
                UserDefaults.standard.set(jsonString, forKey: "personalPowerOverview")
            }
            completion?(PowerInfo(dict: power))
        }, failure: nil)
    }
    
    static func loadBonusClaimOverviewData(completion:((String) -> Void)? = nil) {
        NetworkManager.shared.post(url: APIEndpoint.bonusClaimOverview, success: { data in
            guard let result = data as? [String: Any],
                  let total_disp = result["total_disp"] as? String else {
                completion?("$0.00")
                return
            }
            
            let userInfoModel = UserInfoModel.current
            userInfoModel.totalRevenue = total_disp
            userInfoModel.insertOrReplace()
            
            completion?(total_disp)
        }, failure: nil)
        
    }
    
    
    static func loadPoolPowerOverviewData(pool: String, completion:((PowerInfo) -> Void)? = nil) {
//        if let tokensPrice = UserDefaults.standard.value(forKey: "personalPowerOverview") as? String {
//            if let result = tokensPrice.toObject() as? [String: Any],
//                let power = result["power"] as? [String: Any] {
//                
//                completion?(PowerInfo(dict: power))
//            }
//        }
        
        NetworkManager.shared.post(url: String(format: APIEndpoint.powerInfo, pool), success: { data in
            guard let result = data as? [String: Any] else {
                return
            }
            
//            if let jsonString = result.toJSONString() {
//                UserDefaults.standard.set(jsonString, forKey: "personalPowerOverview")
//            }
            completion?(PowerInfo(dict: result))
        }, failure: nil)
    }
    
}

